package methodCallTreeGen;

import dslProgramGen.DslProgramGen;
import dslProgramGen.GlobalVarTableRecord;
import utils.Utils;

import java.io.FileNotFoundException;
import java.io.FileReader;
import java.util.*;

import static dslProgramGen.newArray.NewArrayObj.genNewArrayObjEqualSignRightStatement;
import static dslProgramGen.newNormalObject.NewNormalObj.genNewNormalObjEqualSignRightStatement;
import static dslProgramGen.util.DslProgramGenUtil.*;
import static utils.Utils.RegularExpressionProcess;
import static utils.Utils.writeLineToDstFile;


/**
 * 生成全局变量表
 */
public class ProcessBeforeMainAndRemovedNodeTraces {
    /**
     * 全局变量表，主要保存main函数前面的变量
     * id -> 记录
     */
    public static Map<String, GlobalVarTableRecord> globalVarTable = new HashMap<>();

    /**
     * 往全局变量表中添加一条新建普通对象记录
     *
     * @param line
     * @param genMainClassName
     * @param varName
     * @param varIndex
     */
    public static void addANormalObjRecordToGlobalVarTable(String line, String genMainClassName, String varName, long varIndex) {
        String objId = RegularExpressionProcess(line, "H:(.*?),");
        String objType = RegularExpressionProcess(line, "C:(.*?)(,|$)");
        objType = renameClassNameReplaceSlashWithUnderlineAndRenameObjectClassName(objType);
        String dslExpr = null;
        if (genMainClassName != null) {
            dslExpr = genMainClassName + "." + varName + "_" + varIndex;
        }
        if (globalVarTable.get(objId) != null) {
//            System.err.println(line + "\tid之前出现过");
            return;
        }
        // 往globalVarTable中添加一条记录
        globalVarTable.put(objId, new GlobalVarTableRecord(objId, objType, dslExpr, null, false));
    }

    /**
     * 往全局变量表中添加一条新建数组对象记录
     */
    public static void addArrayObjRecordToGlobalVarTable(String line, String genMainClassName, String varName, long varIndex, String oneDimArrayLength) {
        String objId = RegularExpressionProcess(line, "H:(.*?),");
        String objType = RegularExpressionProcess(line, "C:(.*?),");
        objType = renameClassNameReplaceSlashWithUnderlineAndRenameObjectClassName(objType);
        String dslExpr = null;
        if (genMainClassName != null) {
            dslExpr = genMainClassName + "." + varName + "_" + varIndex;
        }
        if (globalVarTable.get(objId) != null) {
//            System.err.println(line + "\tid之前出现过");
            return;
        }
        // 往globalVarTable中添加一条记录
        globalVarTable.put(objId, new GlobalVarTableRecord(objId, objType, dslExpr, oneDimArrayLength, false));
    }

    /**
     * 给定一个objId，返回这个id的DSL表示
     *
     * @param objId
     * @return
     */
    public static String objId2objExpr(String objId) {
        if (globalVarTable.get(objId) != null) {
            // 有这个id
            return globalVarTable.get(objId).dslExpr;
        } else {
            // 全局变量表里面没有这个id
            return null;
        }
    }

    /**
     * 判断全局变量表中objId对应的类型是不是java/lang/Class，如果是的话，更改全局变量表该id的类型为newType
     *
     * @param objId
     * @param newType
     */
    public static void checkAndReplaceClassType(String objId, String newType) {
        String oldType = globalVarTable.get(objId).type;
        String javaLangClassType = renameClassNameReplaceSlashWithUnderlineAndRenameObjectClassName("java/lang/Class");
        if (oldType.equals(javaLangClassType)) {
            // 更改全局变量表中该objId的类型为newType
            globalVarTable.get(objId).type = newType;
        }
    }

    /**
     * 读取全局变量的Put和PutA Traces生成对应的Put和PutA DSL语句
     *
     * @param inputFilePath
     * @throws FileNotFoundException
     */
    public static List<String> genGlobalVarPutAndPutADslStatement(String inputFilePath) throws FileNotFoundException {
        List<String> dslStatementList = new ArrayList<>();
        Scanner scanner = new Scanner(new FileReader(inputFilePath));
        while (scanner.hasNextLine()) {
            String line = scanner.nextLine();
            if (Utils.isInputContainsPattern(line, "\\[gc,heap\\s+\\] Put ")) {
                // Put H1:0x000000006d06d69c, C1:java/lang/String, IS:true, H2:0x00000000300ffa5d, C2:[Ljava/io/ObjectStreamField;, F:serialPersistentFields, T:Unknown thread
                // 判断修改的是否是静态字段
                String isStatic = Utils.RegularExpressionProcess(line, "IS:(.*?),");
                // 获得H1的id
                String h1Id = Utils.RegularExpressionProcess(line, "H1:(.*?),");
                // 获得H1的type
                String h1Type = Utils.RegularExpressionProcess(line, "C1:(.*?),");
                h1Type = renameClassNameReplaceSlashWithUnderlineAndRenameObjectClassName(h1Type);
                // 获得H2的id
                String h2Id = Utils.RegularExpressionProcess(line, "H2:(.*?),");
                // 获得H2的type
                String h2Type = Utils.RegularExpressionProcess(line, "C2:(.*?),");
                h2Type = renameClassNameReplaceSlashWithUnderlineAndRenameObjectClassName(h2Type);
                // 获得修改的字段名
                String fieldName = Utils.RegularExpressionProcess(line, "F:(.*?)(,|$)");
                if (isStatic.equals("false")) {
                    // 不是静态字段
                    // 获得h1和h2的dsl表达式
                    if (objId2objExpr(h1Id) != null && objId2objExpr(h2Id) != null) {
                        if (globalVarTable.get(h1Id).isUsed && globalVarTable.get(h2Id).isUsed) {
                            String h1DslExpr = objId2objExpr(h1Id);
                            String h2DslExpr = objId2objExpr(h2Id);
                            String dslStatement = h1DslExpr + "." + fieldName + " = " + h2DslExpr + ";";
                            dslStatementList.add(dslStatement);
                        }
                        // 有可能出现相同的id，但类型不一致的情况，例如之前Add Set root的类型为java/lang/Class，但这里Put的C1为java/lang/Thread
//                        checkAndReplaceClassType(h1Id, h1Type);
//                        checkAndReplaceClassType(h2Id, h2Type);
                    }
                } else {
                    // 修改的是静态字段
                    // 获得C1的类名
                    String c1Type = Utils.RegularExpressionProcess(line, "C1:(.*?),");
                    c1Type = renameClassNameReplaceSlashWithUnderlineAndRenameObjectClassName(c1Type);
                    if (objId2objExpr(h2Id) != null) {
                        if (globalVarTable.get(h2Id).isUsed) {
                            String h2DslExpr = objId2objExpr(h2Id);
                            String dslStatement = c1Type + "." + fieldName + " = " + h2DslExpr + ";";
                            dslStatementList.add(dslStatement);
                        }
                        // 有可能出现相同的id，但类型不一致的情况，例如之前Add Set root的类型为java/lang/Class，但这里Put的C1为java/lang/Thread
//                        checkAndReplaceClassType(h2Id, h2Type);
                    }
                }
            } else if (Utils.isInputContainsPattern(line, "\\[gc,heap\\s+\\] PutA ")) {
                // 如果为PutA
                // PutA H1:0x0000000017f052a3, C1:[Ljava/lang/ThreadGroup;, H2:0x00000000439f5b3d, C2:java/lang/ThreadGroup, O:0, T:Unknown thread,
                // 获得H1的id
                String h1Id = Utils.RegularExpressionProcess(line, "H1:(.*?),");
                // 获得H2的id
                String h2Id = Utils.RegularExpressionProcess(line, "H2:(.*?),");
                // 获得H2的type
                String h2Type = Utils.RegularExpressionProcess(line, "C2:(.*?),");
                h2Type = renameClassNameReplaceSlashWithUnderlineAndRenameObjectClassName(h2Type);
                // 获得修改的index
                String arrayIndex = Utils.RegularExpressionProcess(line, "O:(.*?)(,|$)");
                if (objId2objExpr(h1Id) != null && objId2objExpr(h2Id) != null) {
                    if (globalVarTable.get(h1Id).isUsed && globalVarTable.get(h2Id).isUsed) {
                        String h1DslExpr = objId2objExpr(h1Id);
                        String h2DslExpr = objId2objExpr(h2Id);
                        String dslStatement = h1DslExpr + "[" + arrayIndex + "]" + " = " + h2DslExpr + ";";
                        dslStatementList.add(dslStatement);
                    }
                    // 有可能出现相同的id，但类型不一致的情况，例如之前Add Set root的类型为java/lang/Class，但这里Put的C1为java/lang/Thread
//                    checkAndReplaceClassType(h2Id, h2Type);
                }
            } else {
//                System.err.println("main函数前面的内容出现了未定义的类型");
//                System.err.println(line);
            }

        }
        scanner.close();
        return dslStatementList;
    }

    /**
     * 读取Add Set root,Add Class root,NewS和New生成一张全局变量表
     *
     * @param inputFilePath
     * @param dslStatementList
     * @throws FileNotFoundException
     */
    public static long genGlobalVarTableDslStatement(String inputFilePath, List<String> dslStatementList) throws FileNotFoundException {
        Scanner scanner = new Scanner(new FileReader(inputFilePath));
        long varIndex = 0; // 区分在变量名
        String mainClassName = "Main";
        long mainClassIndex = 0; // 主类index，若一个Main类的静态字段数目超过staticFieldsNumPerMainClass，mainClassIndex++
        String genMainClassName = mainClassName + mainClassIndex; // 生成的程序的主类名
        long staticFieldsNumPerMainClass = 10000; // 每个Main类里的静态字段数目
        String varName = "globalVar";
        while (scanner.hasNextLine()) {
            String line = scanner.nextLine();
            // 如果这行操作是Add Class root或Add Set root
            if (Utils.isInputContainsPattern(line, "\\[gc,heap\\s+\\] (Add Set root|Add Class root)")) {
                // 获得id，type，expr
                // Add Set root H:0x000000006e8cf4c6, Set:VM Global, Size:0, C:[Ljava/lang/Class;, A:0x00007f83b8065b28
                // Add Class root H:0x000000001c20c684, D:unknown, C:java/lang/Class, S:19
                // Add Class root H:0x000000000588ffeb, D:jdk/internal/module/ModuleInfo, C:[Ljava/lang/Object;, Size:61, A:0x000000080003ae08
                String objType = RegularExpressionProcess(line, "C:(.*?),");
                objType = renameClassNameReplaceSlashWithUnderlineAndRenameObjectClassName(objType);
                String objId = RegularExpressionProcess(line, "H:(.*?),");
                String dslExpr = genMainClassName + "." + varName + "_" + varIndex;
                varIndex++;
                if (varIndex == staticFieldsNumPerMainClass) {
                    // 达到一个类最大静态字段数
                    mainClassIndex++;
                    genMainClassName = mainClassName + mainClassIndex;
                    varIndex = 0;
                }
                if (isArrayType(objType)) {
                    // 如果是数组类型
                    // 获得数组大小
                    String arraySize = null;
                    arraySize = RegularExpressionProcess(line, "Size:(.*?),");
                    if (globalVarTable.get(objId) != null) {
//                        System.err.println(line + "\tid之前出现过");
                        continue;
                    }
                    globalVarTable.put(objId, new GlobalVarTableRecord(objId, objType, dslExpr, arraySize, false));
                } else {
                    // 是普通对象类型
                    // 往globalVarTable中添加一条记录
                    if (globalVarTable.get(objId) != null) {
//                        System.err.println(line + "\tid之前出现过");
                        continue;
                    }
                    globalVarTable.put(objId, new GlobalVarTableRecord(objId, objType, dslExpr, null, false));
                }
            } else if (Utils.isInputContainsPattern(line, "\\[gc,heap\\s+\\] NewS ")) {
                // 表示新建java/lang/String类型
                // NewS S:15, H1:0x0000000007530d0a, H2:0x00000000312b1dae
                // byte[] value; [B
                String strId = RegularExpressionProcess(line, "H1:(.*?),");
                String strType = renameClassNameReplaceSlashWithUnderlineAndRenameObjectClassName("java/lang/String");
                String dslStrExpr = genMainClassName + "." + varName + "_" + varIndex;
                varIndex++;
                if (varIndex == staticFieldsNumPerMainClass) {
                    // 达到一个类最大静态字段数
                    mainClassIndex++;
                    genMainClassName = mainClassName + mainClassIndex;
                    varIndex = 0;
                }
                String byteArrayId = RegularExpressionProcess(line, "H2:(.*?)$");
                String byteArrayType = "[B";
                String dslByteArrayExpr = dslStrExpr + ".value";
                String byteArraySize = RegularExpressionProcess(line, "S:(.*?),");
                // 往globalVarTable中添加String对象记录
                globalVarTable.put(strId, new GlobalVarTableRecord(strId, strType, dslStrExpr, null, true));
                // 往globalVarTable中添加byte数组记录
                globalVarTable.put(byteArrayId, new GlobalVarTableRecord(byteArrayId, byteArrayType, dslByteArrayExpr, byteArraySize, true));
            } else if (Utils.isInputContainsPattern(line, "\\[gc,heap\\s+\\] New ")) {
                // 表示新建普通对象或一维数组对象
                // [0.220s][info][gc,heap     ] New H:0x00000000300ffa5d, S:1, C:[Ljava/io/ObjectStreamField;, D:0, T:Unknown thread, MIS:true, M:java/lang/String.<clinit> ()V
                // [0.220s][info][gc,heap     ] New H:0x000000002e817b38, S:2, C:java/lang/String$CaseInsensitiveComparator, T:Unknown thread, MIS:true, M:java/lang/String.<clinit> ()V
                // 先看看trace中 D: 有没有值，以此区分new的是普通对象还是一维数组
                String oneDimArrayLength = Utils.RegularExpressionProcess(line, "D:(.*?)(,|$)");
                if (oneDimArrayLength == null) {
                    // 新建的是普通对象
                    // 添加一条记录
                    addANormalObjRecordToGlobalVarTable(line, genMainClassName, varName, varIndex);
                } else {
                    // 新建的是一维数组对象
                    // [0.220s][info][gc,heap     ] New H:0x00000000300ffa5d, S:1, C:[Ljava/io/ObjectStreamField;, D:0, T:Unknown thread, MIS:true, M:java/lang/String.<clinit> ()V
                    addArrayObjRecordToGlobalVarTable(line, genMainClassName, varName, varIndex, oneDimArrayLength);
                }
                varIndex++;
                if (varIndex == staticFieldsNumPerMainClass) {
                    // 达到一个类最大静态字段数
                    mainClassIndex++;
                    genMainClassName = mainClassName + mainClassIndex;
                    varIndex = 0;
                }
            } else if (Utils.isInputContainsPattern(line, "\\[gc,heap\\s+\\] Put ")) {
                // Put H1:0x000000006d06d69c, C1:java/lang/String, IS:true, H2:0x00000000300ffa5d, C2:[Ljava/io/ObjectStreamField;, F:serialPersistentFields, T:Unknown thread
                // 判断修改的是否是静态字段
                String isStatic = Utils.RegularExpressionProcess(line, "IS:(.*?),");
                // 获得H1的id
                String h1Id = Utils.RegularExpressionProcess(line, "H1:(.*?),");
                // 获得H1的type
                String h1Type = Utils.RegularExpressionProcess(line, "C1:(.*?),");
                h1Type = renameClassNameReplaceSlashWithUnderlineAndRenameObjectClassName(h1Type);
                // 获得H2的id
                String h2Id = Utils.RegularExpressionProcess(line, "H2:(.*?),");
                // 获得H2的type
                String h2Type = Utils.RegularExpressionProcess(line, "C2:(.*?),");
                h2Type = renameClassNameReplaceSlashWithUnderlineAndRenameObjectClassName(h2Type);
                // 获得修改的字段名
                String fieldName = Utils.RegularExpressionProcess(line, "F:(.*?)(,|$)");
                if (isStatic.equals("false")) {
                    // 不是静态字段
                    // 获得h1和h2的dsl表达式
                    if (objId2objExpr(h1Id) != null && objId2objExpr(h2Id) != null) {
                        String h1DslExpr = objId2objExpr(h1Id);
                        String h2DslExpr = objId2objExpr(h2Id);
                        String dslStatement = h1DslExpr + "." + fieldName + " = " + h2DslExpr + ";";
                        dslStatementList.add(dslStatement);
                        // 更新全局变量表是否使用部分
                        globalVarTable.get(h1Id).isUsed = true;
                        globalVarTable.get(h2Id).isUsed = true;
                        // 有可能出现相同的id，但类型不一致的情况，例如之前Add Set root的类型为java/lang/Class，但这里Put的C1为java/lang/Thread
//                        checkAndReplaceClassType(h1Id, h1Type);
//                        checkAndReplaceClassType(h2Id, h2Type);
                    }
                } else {
                    // 修改的是静态字段
                    // 获得C1的类名
                    String c1Type = Utils.RegularExpressionProcess(line, "C1:(.*?),");
                    c1Type = renameClassNameReplaceSlashWithUnderlineAndRenameObjectClassName(c1Type);
                    if (objId2objExpr(h2Id) != null) {
                        String h2DslExpr = objId2objExpr(h2Id);
                        String dslStatement = c1Type + "." + fieldName + " = " + h2DslExpr + ";";
                        dslStatementList.add(dslStatement);
                        // 更新全局变量表是否使用部分
                        globalVarTable.get(h2Id).isUsed = true;
                        // 有可能出现相同的id，但类型不一致的情况，例如之前Add Set root的类型为java/lang/Class，但这里Put的C1为java/lang/Thread
//                        checkAndReplaceClassType(h2Id, h2Type);
                    }
                }
            } else if (Utils.isInputContainsPattern(line, "\\[gc,heap\\s+\\] PutA ")) {
                // 如果为PutA
                // PutA H1:0x0000000017f052a3, C1:[Ljava/lang/ThreadGroup;, H2:0x00000000439f5b3d, C2:java/lang/ThreadGroup, O:0, T:Unknown thread,
                // 获得H1的id
                String h1Id = Utils.RegularExpressionProcess(line, "H1:(.*?),");
                // 获得H2的id
                String h2Id = Utils.RegularExpressionProcess(line, "H2:(.*?),");
                // 获得H2的type
                String h2Type = Utils.RegularExpressionProcess(line, "C2:(.*?),");
                h2Type = renameClassNameReplaceSlashWithUnderlineAndRenameObjectClassName(h2Type);
                // 获得修改的index
                String arrayIndex = Utils.RegularExpressionProcess(line, "O:(.*?)(,|$)");
                if (objId2objExpr(h1Id) != null && objId2objExpr(h2Id) != null) {
                    String h1DslExpr = objId2objExpr(h1Id);
                    String h2DslExpr = objId2objExpr(h2Id);
                    String dslStatement = h1DslExpr + "[" + arrayIndex + "]" + " = " + h2DslExpr + ";";
                    dslStatementList.add(dslStatement);
                    // 更新全局变量表是否使用部分
                    globalVarTable.get(h1Id).isUsed = true;
                    globalVarTable.get(h2Id).isUsed = true;
                    // 有可能出现相同的id，但类型不一致的情况，例如之前Add Set root的类型为java/lang/Class，但这里Put的C1为java/lang/Thread
//                    checkAndReplaceClassType(h2Id, h2Type);
                }
            } else {
//                System.err.println("main函数前面的内容出现了未定义的类型");
//                System.err.println(line);
            }

        }
        scanner.close();
        return mainClassIndex;
    }

    /**
     * 读取Add Set root,Add Class root和New生成一张部分全局变量表，每条记录中的isUsed为false，dslExpr为null，需要在生成MOP程序的时候确定值
     *
     * @param inputFilePath
     * @throws FileNotFoundException
     */
    public static void genPartialGlobalVarTable(String inputFilePath) throws FileNotFoundException {
        Scanner scanner = new Scanner(new FileReader(inputFilePath));
        while (scanner.hasNextLine()) {
            String line = scanner.nextLine();
            // 如果这行操作是Add Class root或Add Set root
            if (Utils.isInputContainsPattern(line, "\\[gc,heap\\s+\\] (Add Set root|Add Class root)")) {
                // 获得id，type，expr
                // Add Set root H:0x000000006e8cf4c6, Set:VM Global, Size:0, C:[Ljava/lang/Class;, A:0x00007f83b8065b28
                // Add Class root H:0x000000001c20c684, D:unknown, C:java/lang/Class, S:19
                // Add Class root H:0x000000000588ffeb, D:jdk/internal/module/ModuleInfo, C:[Ljava/lang/Object;, Size:61, A:0x000000080003ae08
                String objType = RegularExpressionProcess(line, "C:(.*?),");
                objType = renameClassNameReplaceSlashWithUnderlineAndRenameObjectClassName(objType);
                String objId = RegularExpressionProcess(line, "H:(.*?),");
                if (isArrayType(objType)) {
                    // 如果是数组类型
                    // 获得数组大小
                    String arraySize = null;
                    arraySize = RegularExpressionProcess(line, "Size:(.*?),");
                    if (globalVarTable.get(objId) != null) {
//                        System.err.println(line + "\tid之前出现过");
                        continue;
                    }
                    globalVarTable.put(objId, new GlobalVarTableRecord(objId, objType, null, arraySize, false));
                } else {
                    // 是普通对象类型
                    // 往globalVarTable中添加一条记录
                    if (globalVarTable.get(objId) != null) {
//                        System.err.println(line + "\tid之前出现过");
                        continue;
                    }
                    globalVarTable.put(objId, new GlobalVarTableRecord(objId, objType, null, null, false));
                }
            } else if (Utils.isInputContainsPattern(line, "\\[gc,heap\\s+\\] New ")) {
                // 表示新建普通对象或一维数组对象
                // [0.220s][info][gc,heap     ] New H:0x00000000300ffa5d, S:1, C:[Ljava/io/ObjectStreamField;, D:0, T:Unknown thread, MIS:true, M:java/lang/String.<clinit> ()V
                // [0.220s][info][gc,heap     ] New H:0x000000002e817b38, S:2, C:java/lang/String$CaseInsensitiveComparator, T:Unknown thread, MIS:true, M:java/lang/String.<clinit> ()V
                // 先看看trace中 D: 有没有值，以此区分new的是普通对象还是一维数组
                String oneDimArrayLength = Utils.RegularExpressionProcess(line, "D:(.*?)(,|$)");
                if (oneDimArrayLength == null) {
                    // 新建的是普通对象
                    // 添加一条记录
                    addANormalObjRecordToGlobalVarTable(line, null, null, -1);
                } else {
                    // 新建的是一维数组对象
                    // [0.220s][info][gc,heap     ] New H:0x00000000300ffa5d, S:1, C:[Ljava/io/ObjectStreamField;, D:0, T:Unknown thread, MIS:true, M:java/lang/String.<clinit> ()V
                    addArrayObjRecordToGlobalVarTable(line, null, null, -1, oneDimArrayLength);
                }
            }

        }
        scanner.close();

    }

    /**
     * 输出全局变量表到文件中
     * 输出一张全局变量表 globalVarTable.txt
     * 一张Main类字段名 mainClassField.txt
     * 一个Main类静态初始化部分 staticDslBlock.txt
     *
     * @param dstFolderPath
     * @throws FileNotFoundException
     */
    public static void writeGlobalVarTable(String dstFolderPath, List<String> dslStatementList) throws FileNotFoundException {
        // 扫描一遍全局变量表，如果其中的变量使用过，那么对其生成三部分内容 全局变量表 + 类文件的静态字段 + DSL新建对象语句
        String globalVarTableFilePath = dstFolderPath + "globalVarTable.txt";
        for (GlobalVarTableRecord record : globalVarTable.values()) {
            if (record.isUsed) {
                // 如果使用过该变量
                writeLineToDstFile(record.toString(), globalVarTableFilePath);
                // 该记录是否是数组类型
                if (record.arraySize == null) {
                    // 该记录是普通对象类型
                    String dslStatement = record.dslExpr + " = " + genNewNormalObjEqualSignRightStatement(record.type);
                    // 字段名
                    String staticFieldName = record.dslExpr.split("\\.")[1];
                    // 主类名
                    String mainClassName = record.dslExpr.split("\\.")[0];
                    if (DslProgramGen.isGenJavaProgram) {
                        writeLineToDstFile("public static " + record.type + " " + staticFieldName + ";", dstFolderPath + mainClassName + "_mainClassField.txt");
                    } else {
                        writeLineToDstFile("static " + record.type + " " + staticFieldName + ";", dstFolderPath + mainClassName + "_mainClassField.txt");
                    }

                    writeLineToDstFile(dslStatement, dstFolderPath + mainClassName + "_staticDslBlock.txt");
                } else {
                    // 该记录是数组类型
                    // 是普通数组对象
                    String dslStatement = record.dslExpr + " = " + genNewArrayObjEqualSignRightStatement(record.type, record.arraySize);
                    // 字段名
                    String staticFieldName = record.dslExpr.split("\\.")[1];
                    // 主类名
                    String mainClassName = record.dslExpr.split("\\.")[0];
                    if (DslProgramGen.isGenJavaProgram) {
                        writeLineToDstFile("public static " + castArraySignaturToArrayExpr(record.type) + " " + staticFieldName + ";", dstFolderPath + mainClassName + "_mainClassField.txt");
                    } else {
                        writeLineToDstFile("static " + castArraySignaturToArrayExpr(record.type) + " " + staticFieldName + ";", dstFolderPath + mainClassName + "_mainClassField.txt");
                    }

                    writeLineToDstFile(dslStatement, dstFolderPath + mainClassName + "_staticDslBlock.txt");
                }
            }
        }
        // 设置多个新的类，专门运行修改对象引用关系操作，将dslStatementList中的修改对象引用关系操作也写入到该类文件的staticDslBlock.txt文件中
        writeGlobalVarPutAndPutAToMainiClass(dslStatementList, dstFolderPath);
    }

    /**
     * 将全局变量的Put和PutA操作输出到Maini Class文件中
     *
     * @param dslStatementList 所有的Put和PutA语句
     * @param dstFolderPath
     * @return
     */
    public static void writeGlobalVarPutAndPutAToMainiClass(List<String> dslStatementList, String dstFolderPath) {
        // 设置多个新的类，专门运行修改对象引用关系操作，将dslStatementList中的修改对象引用关系操作也写入到该类文件的staticDslBlock.txt文件中
        mainClassIndex++;
        String mainClassName = mainClassNamePre + mainClassIndex;
        // 得创建一个_mainClassField.txt文件
        writeLineToDstFile("", dstFolderPath + mainClassName + "_mainClassField.txt");
        int cnt = 0; // statement语句计数器
        int methodDslStatementNum = 40000; // 一个Maini中包含40000条Put和PutA操作
        for (String dslStatement : dslStatementList) {
            if (cnt == methodDslStatementNum) {
                // 该换一个Maini类了，mainClassIndex++
                mainClassIndex++;
                mainClassName = mainClassNamePre + mainClassIndex;
                // 得创建一个_mainClassField.txt文件
                writeLineToDstFile("", dstFolderPath + mainClassName + "_mainClassField.txt");
                cnt = 0; // statement语句计数器初始化为0
            }
            writeLineToDstFile(dslStatement, dstFolderPath + mainClassName + "_staticDslBlock.txt");
            cnt++;
        }
    }

    public static void main(String[] args) throws FileNotFoundException {
        // 读取beforeMainUsefulTraces.txt文件内容，生成一张全局变量表和静态代码
        String inputFilePath = "src/test/resources/dslProgramGenForComplexMop/filteredTraces/14/beforeMainAndRemovedNodeUsefulTraces.txt";
//        String inputFilePath = "src/test/resources/dslProgramGenForComplexMop/filteredTraces/14/beforeMainUsefulTraces_COPY.txt";
//        String inputFilePath = "src/main/java/preProcessTrace/text.txt";
        String dstFolderPath = "src/test/resources/dslProgramGenForComplexMop/filteredTraces/14/";
//        writeGlobalVarTable(inputFilePath, dstFolderPath);

    }
}
